<?php

namespace App\Http\Controllers\Payment;

use App\Http\Controllers\Controller;
use App\Jobs\IssueInvoice;
use App\Models\App\AppUser;
use App\Models\Common\ApiResponse;
use App\Models\Common\BaseModel;
use App\Models\Common\Constant;
use App\Models\Invoice\Invoice;
use App\Models\Invoice\GoodDetail;
use App\Models\Invoice\Subject;
use App\Models\Invoice\Title;
use App\Models\ParkingLot\MthOrder;
use App\Models\ParkingLot\ParkOrder;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;

class InvoiceController extends Controller
{

    public $name = '开票管理';

    public function issue(Request $request)
    {
        $this->parkingLotID = $parkingLotID = getParkingLotID(requestSource() === Constant::SOURCE_APP);

        if (!Subject::where('parking_lot_id', $parkingLotID)->where('enabled', true)->exists()) {
            return ApiResponse::fail('未配置可用的开票主体或开票主体未启用');
        }

        if ($request->get('related_type') === GoodDetail::CATEGORY_TMP_PAYMENT) {
            $baseQuery = ParkOrder::where('parking_lot_id', $parkingLotID);
            $invoiceGoodDetailQuery = GoodDetail::query()->where('category', GoodDetail::CATEGORY_TMP_PAYMENT);
        } elseif ($request->get('related_type') === GoodDetail::CATEGORY_MONTHLY_PAYMENT) {
            $baseQuery = MthOrder::where('parking_lot_id', $parkingLotID);
            $invoiceGoodDetailQuery = GoodDetail::query()->where('category', GoodDetail::CATEGORY_MONTHLY_PAYMENT);
        } else {
            return ApiResponse::fail('订单类型选择错误');
        }

        $relatedIDs = array_filter(array_unique(explode(',', $request->get('related_ids'))));

        if (!count($relatedIDs)) {
            return ApiResponse::fail('待开票订单标识必填');
        }

        if (!$invoiceGoodDetailQuery->where('parking_lot_id', $parkingLotID)->exists()) {
            return ApiResponse::fail('开票申请提交失败,未配置开票商品');
        }

        if (!Subject::where('parking_lot_id', $parkingLotID)->where('enabled', true)->exists()) {
            return ApiResponse::fail('开票申请提交失败,未配置开票主体');
        }

        $baseQuery = $baseQuery->whereIn('id', $relatedIDs);

        switch ($source = requestSource()) {
            case Constant::SOURCE_APP:
                if (!$user = appUser()) {
                    return ApiResponse::fail('获取当前登录用户信息失败');
                }
                $appUserID = $user->id;
                $this->needLogging = false;
                $orders = $baseQuery->where('app_user_id', $user->id)->get();
                break;
            case Constant::SOURCE_ADMIN:
            default:
                $this->admin = $user = admin();
                $source = Constant::SOURCE_ADMIN;
                //校验权限
                $orders = $baseQuery->get();

                $appUserIDs = $orders->pluck('app_user_id')->unique();
                if ($appUserIDs->count() !== 1) {
                    return ApiResponse::fail('订单的所属的用户不同,不可一起开票');
                }
                $appUserID = $appUserIDs->first();
                $this->logContent = '开具发票';
                break;
        }

        if (!$orders->count()) {
            return ApiResponse::fail('待开票订单不得为空');
        }

        if ($orders->count() !== count($relatedIDs)) {
            return ApiResponse::fail('待开票订单数量与上送订单标识数量不一致');
        }

        foreach ($orders as $order) {
            if ($order->refund_amount) {
                return ApiResponse::fail("订单({$order->order_title})存在退款记录,不可开票");
            }
        }

        $invoiceBook = Invoice::query()->with(['reversed'])->where('status', Invoice::STATUS_SUCCESS)->whereIn('paid_code', $orders->pluck('paid_code')->toArray())->get();

        foreach ($invoiceBook as $invoice) {
            if ($invoice->reversed) {
                continue;
            }
            return ApiResponse::fail('部分订单已开具发票,不可重复申请开具发票');
        }

        $title = null;
        if ($titleID = $request->get('title_id')) {
            $title = Title::find($titleID);
        }

        if (!$title) {
            $title = Title::getDefaultTitle($appUserID);
        }

        foreach ($orders as $order) {
            IssueInvoice::dispatch($order, $title, $source)->onQueue(Constant::QUEUE_MIXED);
        }
        return ApiResponse::return('发票开具申请已收到');
    }

    public function index(Request $request)
    {
        $parkingLotID = getParkingLotID(requestSource() === Constant::SOURCE_APP);
        $baseQuery = Invoice::with(['related'])->where('parking_lot_id', $parkingLotID)->orderByDesc('updated_at');

        $page = intval($request->get('page') ?: 1);
        $perPage = intval($request->get('per_page') ?: 10);

        switch (requestSource()) {
            case Constant::SOURCE_APP:
                if (!$user = appUser()) {
                    return ApiResponse::fail('获取当前登录用户信息失败');
                }
                $baseQuery->where('app_user_id', $user->id);
                $this->needLogging = false;
                break;
            case Constant::SOURCE_ADMIN:
            default:
//                $this->admin = $user = admin();
//                $this->logContent = '查看发票记录';
                //权限
                break;
        }

        if ($code = $request->get('code')) {
            $baseQuery->where('code', $code);
        }

        if ($number = $request->get('number')) {
            $baseQuery->where('number', $number);
        }

        if ($status = $request->get('status')) {
            $baseQuery->where('status', $status);
        }

        if ($appUserPhone = $request->get('app_user_phone')) {
            $appUser = AppUser::where('phone', $appUserPhone)->first();
            $baseQuery->where('app_user_id', optional($appUser)->id);
        }

//        $paginationDat = $baseQuery->paginate(intval($request->get('per_page')), '*', 'page', intval($request->get('page')));

        $paginationDat = BaseModel::getList($baseQuery, $page, $perPage);

        return ApiResponse::return('', $paginationDat);
    }

    public function show($id)
    {

        $parkingLotID = getParkingLotID(requestSource() === Constant::SOURCE_APP);
        $baseQuery = Invoice::with(['related']);

        switch (requestSource()) {
            case Constant::SOURCE_APP:
                if (!$user = appUser()) {
                    return ApiResponse::fail('获取当前登录用户信息失败');
                }
                $baseQuery->where('app_user_id', $user->id);
                $this->needLogging = false;
                break;
            case Constant::SOURCE_ADMIN:
            default:
//                $this->admin = $user = admin();
//                $this->logContent = '查看发票详情';
                //权限
                break;
        }

        $invoice = $baseQuery->where('parking_lot_id', $parkingLotID)->findOrFail($id);
        return ApiResponse::return('', $invoice);
    }

    public function aggregate(Request $request)
    {
        $user = admin();
        $parkingLotID = getParkingLotID();
//        $this->logContent = '访问了发票汇总';
        $datPacket = [];
        $baseQuery = Invoice::where('parking_lot_id', $parkingLotID)->where('status', Invoice::STATUS_SUCCESS);

        if ($paidAtBegan = $request->get('paid_at_began')) {
            try {
                $paidAtBegan = Carbon::parse($paidAtBegan)->toDateTimeString();
                $baseQuery->where('paid_at', '>=', $paidAtBegan);
            } catch (\Throwable $exception) {
                return ApiResponse::fail('起始支付时间格式错误');
            }
        }

        if ($paidAtEnded = $request->get('paid_at_ended')) {
            try {
                $paidAtEnded = Carbon::parse($paidAtEnded)->toDateTimeString();
                $baseQuery->where('paid_at', '<=', $paidAtEnded);
            } catch (\Throwable $exception) {
                return ApiResponse::fail('截止支付时间格式错误');
            }
        }

        $goodDetails = GoodDetail::query()->where('parking_lot_id', $parkingLotID)->pluck('tax_rate', 'category');

        foreach (GoodDetail::CATEGORY_NAMES as $category => $name) {

            $categoryQuery = (clone $baseQuery);

            if ($category === GoodDetail::CATEGORY_TMP_PAYMENT) {
                $categoryQuery->where('related_type', ParkOrder::class);
            } else {
                $categoryQuery->where('related_type', MthOrder::class);
            }

            $invoiceDetails = $categoryQuery->first([DB::raw('sum(amount) as amount'), DB::raw('sum(total_amount) as total_amount'), DB::raw('sum(tax_amount) as tax_amount')])->toArray();

            $datPacket[] = [
                'name' => $name,
                'tax_rate' => strval(floatval(\Arr::get($goodDetails, $category))),
                'amount' => strval(floatval(\Arr::get($invoiceDetails, 'amount'))),
                'total_amount' => strval(floatval(\Arr::get($invoiceDetails, 'total_amount'))),
                'tax_amount' => strval(floatval(\Arr::get($invoiceDetails, 'tax_amount')))
            ];
        }

        return ApiResponse::return('', $datPacket);
    }
}
